ICTSC9のバックボーン解説 - OpenStack編

ICTSC9 では問題 VM およびライフサーバ等の基盤としてオープンソースのプライベートクラウド基盤である OpenStack を使いました。バージョンは OpenStack Pike です。以下では、今回の OpenStack でどのような構成をとったかを解説します。

全体

OpenStack は疎結合な複数のコンポーネントの組み合わせからなります。今回使った主なものは以下の通りです。

  • Nova: VM を扱う
  • Neutron: ネットワークを扱う
  • Cinder: ブロックストレージを扱う
  • Glance: VM のディスクイメージを扱う

OpenStack については公式のインストールガイドを読むと、全体像および各コンポーネントについて理解しやすいです。

物理サーバは6台使いました。具体的には以下の通りです。全て CyberAgent さんからお借りしました。

名前 型番 CPU メモリ ディスク Fusion IO 用途
ictsc-m4-01 IBM System x3530 M4 24cores 192GB 1200GB(RAID10) 1200GB compute
ictsc-m4-02 IBM System x3530 M4 24cores 192GB 600GB(RAID1) 1200GB controller
ictsc-m4-03 IBM System x3530 M4 24cores 192GB 600GB(RAID1) 1200GB compute
ictsc-m4-04 IBM System x3530 M4 24cores 192GB 1200GB(RAID10) 600GB compute
ictsc-m4-05 IBM System x3530 M4 24cores 192GB 1200GB(RAID10) 600GB compute
ictsc-m4-06 IBM System x3530 M4 24cores 192GB 1200GB(RAID10) 600GB compute

用途に “compute” と書いてあるのは、実際にその上で VM を動かしているサーバです。これらのサーバでは Nova と Neutron の一部の機能を担うプロセスが動いています。”controller” は OpenStack 全体を管理するためのプロセスを動かしているサーバです。上述したコンポーネント全ての、主要なプロセスが動いています。また、今回の構成では、 controller 上で VM が動いていません。

Fusion IO については Nova の部分で説明します。

Nova: VM

今回 VM のディスクには Fusion IO という高速なディスクを用いました。各 compute サーバの
PCI Express スロットに Fusion IO を挿し、Nova の設定によって VM のディスクをマウントした Fusion IO 上に作るようにしました。これにより IO の負荷の軽減を実現しました。

ICTSC では、毎回数百台単位の VM を動かしています。今回、問題 VM は1チーム22台だったため、合計で 22 x 15 = 330 台ありました。これに加えて、DNS サーバ、監視サーバ、そしてコンテストサイト用の VM があります。全てを合計すると、メモリが 304GB 、 CPU が 365cores 、ディスクが 2.9TB が必要でした。通常は、オーバーコミットという技術を使って、物理リソース以上のリソースを VM が合計で使えるようにします。今回は compute 5台合計で CPU 120cores 、メモリ 960GB 、 Fusion IO 4.2TB でした。このため、ディスクとメモリについてはオーバーコミットが必要ありませんでした。

VM は複数のサーバ上に分散して配置されます。ICTSC9 では、問題ごとにサーバを分けました。つまり、ある1つの問題の VM は全チーム分が同じサーバで動いています。これにより、特定のサーバの電源が落ちた際に、チームごとに解けなくなる問題が異なるという、不平等が生じないようにしています(もっとも、ICTSC9 の1日目の午前中のように全てのサーバが落ちてしまえば関係ありませんが)。

Neutron: ネットワーク

ICTSC では、各チームが複数の問題を解くことになります。そして、一部の問題は特定の問題が解かれないと公開されません。そこで、各チームの各問題ごとに L2 ネットワークが分断されている必要があります。他のチームの VM や、まだ公開されていない問題の VM にアクセスできてしまうと問題があるからです。

今回、問題 VM のネットワーク構成には VLAN を使いました。各チームの各問題に別々の VLAN ID を割り当てました。

Neutron は、VLAN を使ったネットワーク構成を標準的にサポートします。実装には LinuxBridge を使うか OpenVSwitch を使うか選ぶことができます。今回は LinuxBridge を使いました。これは、OpenStack 担当者が個人的に慣れておりデバッグがしやすいからという理由のためです。

LinuxBridge での VLAN ネットワークは、以下のように構成されます。

  • VLAN ID に対して、物理インターフェースに紐づいた VLAN インターフェースが作成される
  • VLAN インターフェースがその VLAN 用の bridge に接続される
  • VM が bridge に接続される

今回は、「冗長化」がテーマということで、物理 NIC はボンディングしました。そのため、ボンディングインターフェースに紐づいた VLAN インターフェースが作成されるという形になりました。なお、ボンディングしたポートの片方が IPMI 兼用のポートだったため、IPMI の監視ができなくなるという問題が発生しました。これは諦めざるを得ませんでした。

基本的に VM の IP アドレスは DHCP によって割り当てられます。ただし、オプションにより VM に割り当てる IP アドレスを指定することができます。今回は、これを用いて VM の IP アドレスを固定しました。DHCP サーバは OpenStack によって提供されます。具体的には controller で動いている dnsmasq のプロセスです。

ルーティングには物理ネットワーク機器を用いました。基本的に VM のデフォルトゲートウェイには物理機器のインターフェースの IP アドレスを設定しました。OpenStack が提供するソフトウェアルータを使うこともできるのですが、パフォーマンスの問題等から使っていません。

以上で説明した構成を、図に示しました。簡単のためチームを2つ、問題 VM を1台に絞るなどの簡略化をしています。

ネットワークに関する留意事項として、デフォルトでは Neutron が勝手に様々なセキュリティ設定を入れてしまうということがあります。Neutron は iptables や ebtables を駆使して、不審なパケットをフィルタリングしてしまいます。具体的には VM が DHCP を出せなかったり、ルーティングできなかったり、MAC アドレスの書き換えができなかったりします。ICTSC にとって、これは全くもって余計なお世話です。そこで、”disable port security” というお節介なセキュリティを無効にする設定を入れる必要があります。

Cinder: ブロックストレージ

Cinder はネットワークマウント可能なブロックストレージを提供します。デフォルトでは LVM と iSCSI を組み合わせて使います。VM にブロックストレージをアタッチすることで、ライブマイグレーションが可能になるなどのメリットがあります。

分散ストレージ技術である Ceph を Cinder と連携させることもできます。これにより VM のストレージの冗長化を行うことが期待できます。ICTSC9 でも Ceph + Cinder 構成を行おうとしたのですが、検証途中で諦めました。

最終的には Cinder によってコンテストサイトのためのブロックストレージを提供することになりました。compute の Fusion IO は Nova が使っているので controller の Fusion IO のみを Cinder 用に使いました。

Glance: ディスクイメージ

VM を起動するにはディスクイメージが必要です。Glance はこのイメージの作成、編集、削除を行うコンポーネントです。

問題を検証する段階では、 OS がインストールされている状態のベースイメージをもとに、各々がパッケージを導入し設定ファイルを編集して問題を作っていきます。このベースイメージは、インターネット上で公開されている qcow2 形式のファイルを使います。

問題が出来上がると、各々が設定を行った VM 自体をイメージ化します。こうして用意されたイメージから VM を起動することで、プロビジョニングなしに問題 VM を作成することができます。ただし IP アドレスのハードコードを行う問題もあるので、同じ問題の VM は全てのチームで同じ IP アドレスにせざるを得ません。すると IP アドレスだけでは異なるチームの VM を区別できないという問題が生じます。これは、バックボーンネットワーク側で NAVT という技術によって解決されます。詳しくは NAVT の解説を参照してください

VM の大量展開

22台 x 15チーム分の VM を手動で展開するのは正気の沙汰ではありません。そこで ICTSC では VM の展開を自動化しています。

ICTSC9 では Ansible を使って VM の大量展開を行いました。シェルスクリプトでも自動化はできるのですが、 Ansible は冪等性を保証してくれるというメリットがあります。ただし、 Ansible は遅いので、全 VM の展開には数時間かかります。

Ansible の OpenStack モジュールでネットワークの作成から VM の起動までを行います。ディスクイメージの節で説明した通り、起動した時点で問題として成立するようになっているので、基本的にはプロビジョニングは不要です。

なお ICTSC9 本番二日前に大量展開を行った際、サーバへの VM の割り振りが偏っていたことが原因でディスクの不足が生じ、一部 VM の起動に失敗してしまいました。そこで状態が ERROR になっている VM を削除し、ディスクのオーバーコミット設定を行った上で、それらの VM のみを再び展開することにしました。その際の bash の history を抜粋したものが以下です。


 1944  openstack server list | grep ERROR
 1945  openstack server list | awk '{ print $2 }'
 1949  openstack server list |  awk 'NR > 1 { print $2 }'
 1951  openstack server list |  awk 'NR > 3 { print $2 }' | xargs openstack server delete

VM 一覧を取得する openstack server list をパイプし awk と xargs を駆使することで ERROR の VM だけを消そうとしていますね。ところが二行目以降では肝心の grep ERROR が抜けています。結果として、全ての VM が吹き飛びました。これに気づいた担当者は、顔面蒼白でモスバーガーも喉を通らない状態になりました。その後、全 VM を再び展開しなおす羽目になりましたが、なんとか本番に間に合わせることができました。

おわりに

ICTSC9 での OpenStack についての解説は以上です。今回の構成は ICTSC6-8 での経験と反省を踏まえたものになっています。構築中にいくつかトラブルはありましたが、基本的にはちゃんと動いていたので良かったです。

今回は6台ものサーバに加えて Fusion IO も使うことができたため、余裕を持ってリソースを使うことができました。機材を貸してくださった CyberAgent さん、本当にありがとうございました。